package net.liteheaven.xblib.common.io;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.os.Build;

import net.liteheaven.xblib.common.convert.FileSizeUtil;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 
 * 安卓内存获取工具类 
 * @author  LiangYu
 * @data:  2015-3-26 下午6:25:17 
 * @version:  V1.0
 */
public class MemUtil {

	private static final String TAG = "MemUtil";

    /**
     * 获取内存总量
     * @return 单位（KB）
     */
	public static long getTotalMemory() {

		String fileName = "/proc/meminfo";
		String line = "";
		long ret = 0;

		BufferedReader localBufferedReader = null;
		try {
			FileReader fr = new FileReader(fileName);
			localBufferedReader = new BufferedReader(fr, 8192);
			while ((line = localBufferedReader.readLine()) != null) {
				ret = getTotalMemInMeminfo(line);
				if (ret != 0) {
					break;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (localBufferedReader != null) {
				try {
					localBufferedReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return ret;
	}

	private static long getTotalMemInMeminfo(String src) {
		String copy = src.toLowerCase();
		copy = copy.replace(" ", "");
		long ret = 0;
		Pattern p = Pattern.compile("(memtotal:)([0-9]+)(kb)");
		Matcher m = p.matcher(copy);
		if (m.find()) {
			String out = m.group(2);
			ret = Long.valueOf(out);
		}
		return ret;
	}

    /**
     * 获取可用内存百分比
     * @param ctx
     * @return
     */
	public static int getAvaMemPercentage(Context ctx){
		
		long total = getTotalMemory() * 1024;		
		long ava = getAvailMemory(ctx);
		int percentage = (int) (ava * 100 / total);
		return percentage;
	}

    /**
     * 获取可用内存总量
     * @param context
     * @return 单位（B）
     */
	public static long getAvailMemory(Context context){
		
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
        am.getMemoryInfo(mi);
        return mi.availMem;
    }
	
	/**
	 * 
	 * 清理进程
	 * 
	 * 参考：http://www.aichengxu.com/view/9122
	 * 我这里选择阈值是IMPORTANCE_VISIBLE级别的，也就是非可见的后台进程和服务会被杀掉（一些系统进程肯定除外）。
	 * 清理的效果跟金山清理大师和360桌面的一键清理效果差不多。
	 * 如果不想杀的太凶，可以选择IMPORTANCE_SERVICE级别，杀掉那些长时间没用或者空进程了，
	 * 这个级别的清理力度不够大，达不到金山清理大师的效果。
	 *  
	 * @throw 
	 * @return void
	 */
	public static String cleanUp(Context ctx, List<String> whiteList){
		
		StringBuffer report = new StringBuffer();
		
		//To change body of implemented methods use File | Settings | File Templates.
        ActivityManager am = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningAppProcessInfo> infoList = am.getRunningAppProcesses();
        List<ActivityManager.RunningServiceInfo> serviceInfos = am.getRunningServices(100);

        long beforeMem = getAvailMemory(ctx);
        report.append("===== cleanUp start =====\n");
        report.append("mem = " + FileSizeUtil.getFileSizeText(beforeMem) +"\n");
        int count = 0;
        if (infoList != null) {
            for (int i = 0; i < infoList.size(); ++i) {
            	
            	StringBuffer killSb = new StringBuffer();
            	
                RunningAppProcessInfo appProcessInfo = infoList.get(i);
                
                killSb.append("---ps = " + appProcessInfo.processName + "\n");
                //killSb.append("im = " + appProcessInfo.importance + "\n");

                if (appProcessInfo.importance > RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
                	
                	//killSb.append("kill = true\n");
                    String[] pkgList = appProcessInfo.pkgList;
                    //killSb.append("PackageCount = " + pkgList.length + "\n");
                    
                    for (int j = 0; j < pkgList.length; ++j) {
                    	
                    	String pkg = pkgList[j];

                    	boolean isInWhiteList = whiteList.contains(pkg);
                    	//killSb.append("" + (j+1) +".pkg = " + pkg + " white =" + isInWhiteList + "\n");
                        if (!isInWhiteList) {
                        	am.killBackgroundProcesses(pkgList[j]);
                        	count++;
                        }
                    }
                    report.append(killSb);
                }
                else{
                	killSb.append("kill = false\n");
                }

            }
        }

        long afterMem = getAvailMemory(ctx);
        report.append("mem = " + FileSizeUtil.getFileSizeText(afterMem) + "\n");
        report.append(""+count+" progress cleaned!\n");
        
        long reduce = afterMem - beforeMem;
        if (reduce < 0){
        	reduce = 0;
        }
        String sizeText = FileSizeUtil.getFileSizeText(reduce).toString();
        report.append(""+sizeText+" memory released!\n");
        return report.toString();
	}

	private void cleanUpEx(){
		if (Build.VERSION.SDK_INT >= 21){

		}
	}

	private String[] getActivePackages(Context ctx) {
		final Set<String> activePackages = new HashSet<String>();
		ActivityManager am = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
		final List<ActivityManager.RunningAppProcessInfo> processInfos = am.getRunningAppProcesses();
		for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) {
			if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
				activePackages.addAll(Arrays.asList(processInfo.pkgList));
			}
		}
		return activePackages.toArray(new String[activePackages.size()]);
	}
}
